/*
 * nokia-5110.c
 *
 *  Created on: Nov 15, 2013
 *      Author: Ahmed
 */

#include "stm32f10x.h"
#include "nokia-5110.h"
#include "spieeprom.h"
#include "font.h"
#include "main.h"

void LCD5110_GPIO_Config(void);
void LCD5110_DC(unsigned char);
void LCD5110_CS(unsigned char);
void LCD5110_RST(unsigned char);

void LCD5110_init()
{
	LCD5110_GPIO_Config();

	LCD5110_DC(1);//LCD_DC = 1; Send Data
	LCD5110_CS(1);//SPI_CS = 1;

	LCD5110_RST(0);//LCD_RST = 0;
	Delay(10);
	LCD5110_RST(1);//LCD_RST = 1;

//	00100001 power down control; entry mode; extended instruction set control (H)=1
//	0 0 0 1 0 0 PD V H
//	PD=0 chip is active		PD=1 power down mode.
	LCD5110_LCD_write_byte(0x21,0);	// Extended Instructions
//	11000110 write VOP to register 0 1 VOP6 VOP5 VOP4 VOP3 VOP2 VOP1 VOP0
	LCD5110_LCD_write_byte(0xc6,0);
//	00000110 set Temperature Coefficient 0 0 0 0 0 0 1 TC1 TC0
	LCD5110_LCD_write_byte(0x06,0);
//	00010011 set Bias System (BSx) 0 0 0 0 1 0 BS2 BS1 BS0
	LCD5110_LCD_write_byte(0x13,0);

//	00100000 power down control; entry mode; extended instruction set control (H)=0
//	So that we can move to x,y positions
	LCD5110_LCD_write_byte(0x20,0);	//a command byte.
//	00001100 sets display configuration	00001D0E
//	D and E
//	00 display blank
//	10 normal mode
//	01 all display segments on
//	11 inverse video mode
	LCD5110_LCD_write_byte(0x0c,0);	//a command byte.
}

void LCD5110_LCD_write_byte(unsigned char dat,unsigned char mode)
{
//	unsigned char i;

	LCD5110_CS(0);	//SPI_CS = 0;

	if (mode == 0)
		LCD5110_DC(0);//LCD_DC = 0;	//a command byte.
	else
		LCD5110_DC(1);//LCD_DC = 1;	//a data byte.

	spi_WriteByte(dat);
	LCD5110_CS(1);//SPI_CS = 1;		// chip is not selected

}

void LCD5110_write_char(unsigned char c)
{
	unsigned char line;
	unsigned char ch = 0;

	c = c - 32;

	for(line=0;line<6;line++)
	{
		ch = font6_8[c][line];
		LCD5110_LCD_write_byte(ch,1);	//write a data byte

	}
}

void LCD5110_write_char_rev(unsigned char c)
{
	unsigned char line;
	unsigned char ch = 0;

	c = c - 32;

	for(line=0;line<6;line++)
	{
		ch = ~font6_8[c][line];
		LCD5110_LCD_write_byte(ch,1);

	}
}


void LCD5110_write_string(char *s)
{
	unsigned char ch;
  	while(*s!='\0')
	{
		ch = *s;
		LCD5110_write_char(ch);
		s++;
	}
}

void LCD5110_write_string_rev(char *s)
{
	unsigned char ch;
  	while(*s!='\0')
	{
		ch = *s;
		LCD5110_write_char_rev(ch);
		s++;
	}
}


void LCD5110_clear()
{
	unsigned char i,j;
	for(i=0;i<6;i++)
		for(j=0;j<84;j++)
			LCD5110_LCD_write_byte(0,1);
}

void LCD5110_set_XY(unsigned char X,unsigned char Y)
{
	unsigned char x;
	x = 6*X;

	LCD5110_LCD_write_byte(0x40|Y,0);		// a command byte
	LCD5110_LCD_write_byte(0x80|x,0);
}

/*
 * Takes an integer and display it as ascii on the LCD
 * state: normal or reverse Video
 * leading: how may digits to display from the right side
 * 			if zero that means display the full number without leading zeros
 */
void LCD5110_Write_Dec(uint16_t b, uint8_t state, uint8_t digit_num)
{

	unsigned char datas[5],i,j;

	datas[0] = b/10000;
	b = b - datas[0]*10000;
	datas[1] = b/1000;
	b = b - datas[1]*1000;
	datas[2] = b/100;
	b = b - datas[2]*100;
	datas[3] = b/10;
	b = b - datas[3]*10;
	datas[4] = b;

	datas[0]+=48;
	datas[1]+=48;
	datas[2]+=48;
	datas[3]+=48;
	datas[4]+=48;

	/* find the first non zero digit to display - display at least one digit */
	for (i = 0; i < 5; i++) {
		if (datas[i] != 48) {
			break;
		}
	}

	if (digit_num > 0 && digit_num < 6){	// valid range
		i = 5-digit_num;
	}

	for (j = i; j < 5; j++) {
		if (state == NORMAL) {
			LCD5110_write_char(datas[j]);
		} else {
			LCD5110_write_char_rev(datas[j]);
		}
	}
}

/*
 *  RST	(Pin 1)				PA2
 *	CS	(Pin 2)				PA3
 *	DC ( Pin 3)				PA4
 */
void LCD5110_GPIO_Config()
{
	GPIO_InitTypeDef GPIOA_Init;

	GPIOA_Init.GPIO_Pin = GPIO_Pin_2 |GPIO_Pin_3 |GPIO_Pin_4;
	GPIOA_Init.GPIO_Speed = GPIO_Speed_10MHz;
	GPIOA_Init.GPIO_Mode = GPIO_Mode_Out_PP;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_Init(GPIOA,&GPIOA_Init);
}

void LCD5110_CS(unsigned char temp)
{
	if (temp) GPIO_SetBits(GPIOA,GPIO_Pin_3);
	else GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}

void LCD5110_RST(unsigned char temp)
{
	if (temp) GPIO_SetBits(GPIOA,GPIO_Pin_2);
	else GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}

void LCD5110_DC(unsigned char temp)
{
	if (temp) GPIO_SetBits(GPIOA,GPIO_Pin_4);
	else GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
